home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Frameworks / Hsoi's App Shell 1.0a4 / HAS Other Source / WASTE 1.3a4 Distribution / WASTE 1.3a4 / Source / WEFontTables.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-04-04  |  8.6 KB  |  342 lines  |  [TEXT/CWIE]

  1. /*
  2.  *    WEFontTables.c
  3.  *
  4.  *    WASTE PROJECT
  5.  *  Font Mapping Tables
  6.  *
  7.  *  Copyright (c) 1993-1997 Marco Piovanelli
  8.  *    All Rights Reserved
  9.  *
  10.  *  C port by Dan Crevier
  11.  *
  12.  */
  13.  
  14.  
  15. #include "WASTEIntf.h"
  16.  
  17. enum
  18. {
  19.     weFontTableSignature            =    'FISH',
  20.     weCurrentFontTableVersion        =    0x01008000        //    1.0
  21. };
  22.  
  23. typedef struct
  24. {
  25.     FourCharCode ftSignature;    //    must be weFontTableSignature
  26.     UInt32 ftVersion;            //    font table version, in NumVersion format
  27.     UInt32 ftNumEntries;        //    entry count
  28.     UInt32 ftReserved;            //    reserved for future use
  29. } WEFontTableHeader, *WEFontTableHeaderPtr;
  30.  
  31. typedef struct
  32. {
  33.     SInt16 ftOldFontID;        //    font ID on save
  34.     SInt16 ftNewFontID;        //    font ID on re-open
  35.     SInt32 ftEncoding;        //    character encoding (currently = script code)
  36.     SInt32 ftReserved;        //    reserved for future use
  37.     UInt32 ftNameOffset;    //    offset to font name
  38. } WEFontTableEntry, *WEFontTableEntryPtr;
  39.  
  40. typedef struct
  41. {
  42.     WEFontTableHeader ftHeader;
  43.     WEFontTableEntry ftEntries [ kVariableLengthArray ];
  44.     //    packed font names follow
  45. } WEFontTable, *WEFontTablePtr, **WEFontTableHandle;
  46.  
  47. pascal OSErr WEBuildFontTable(Handle hFontTable, WEFontIDToNameUPP fontIDToNameProc, WEHandle hWE)
  48. {
  49.     Handle hStyles = nil;
  50.     WEStyleTableEntry *pStyle, *pStyle2;
  51.     WEFontTablePtr pFontTable;
  52.     SInt32 nStyles, styleIndex, styleIndex2;
  53.     WEFontTableEntry entry;
  54.     WEFontTableEntryPtr pEntry;
  55.     Str255 fontName;
  56.     SInt32 fontCount;
  57.     SInt32 fontNameOffset;
  58.     Size fontNameSize, offsetAdjustment;
  59.     Boolean saveStylesLock;
  60.     OSErr err;
  61.  
  62.     //    return an error code is hFontTable is nil
  63.     err = nilHandleErr;
  64.     if (hFontTable == nil)
  65.     {
  66.         goto cleanup;
  67.     }
  68.  
  69.     //    clone the style table, as we need a modifiable copy
  70.     hStyles = (Handle) (*hWE)->hStyles;
  71.     if ((err = HandToHand(&hStyles)) != noErr)
  72.     {
  73.         hStyles = nil;
  74.         goto cleanup;
  75.     }
  76.  
  77.     //    lock the style table
  78.     saveStylesLock = _WESetHandleLock(hStyles, true);
  79.  
  80.     //    fill in font table header
  81.     SetHandleSize(hFontTable, sizeof(WEFontTableHeader));
  82.     if ((err = MemError()) != noErr)
  83.     {
  84.         goto cleanup;
  85.     }
  86.     pFontTable = * (WEFontTableHandle) hFontTable;
  87.     _WEBlockClr(pFontTable, sizeof(WEFontTableHeader));
  88.     pFontTable->ftHeader.ftSignature = weFontTableSignature;
  89.     pFontTable->ftHeader.ftVersion = weCurrentFontTableVersion;
  90.  
  91.     //    init counters
  92.     fontCount = 0;
  93.     fontNameOffset = sizeof(WEFontTableHeader);
  94.  
  95.     //    walk the style table
  96.     nStyles = (*hWE)->nStyles;
  97.     for (    styleIndex = 0,
  98.             pStyle = (WEStyleTableEntry *) *hStyles;
  99.             styleIndex < nStyles;
  100.             styleIndex++, pStyle++ )
  101.     {
  102.         //    skip this style table entry if it's either unused
  103.         //    or it references a font we have already processed
  104.         if (pStyle->refCount == 0)
  105.         {
  106.             continue;
  107.         }
  108.  
  109.         //    get the name of this font
  110.         BLOCK_CLR(fontName);
  111.         GetFontName(pStyle->info.runStyle.tsFont, fontName);
  112.  
  113.         //    caller can customize the building process by supplying
  114.         //    a mapping function
  115.         if (fontIDToNameProc != nil)
  116.         {
  117.             if ((err = CallWEFontIDToNameProc(pStyle->info.runStyle.tsFont, fontName, fontIDToNameProc)) != noErr)
  118.             {
  119.                 goto cleanup;
  120.             }
  121.         }
  122.  
  123.         //    calculate the space needed by the font name
  124.         //    for optimal alignment, make sure it's a multiple of 4
  125.         fontNameSize = StrLength(fontName) + 4;
  126.         fontNameSize &= ~3;
  127.  
  128.         //    append font name at the end of the font table
  129.         if ((err = _WESplice(hFontTable, fontName, fontNameSize, -1)) != noErr)
  130.         {
  131.             goto cleanup;
  132.         }
  133.  
  134.         //    create a new font table entry for this font
  135.         BLOCK_CLR(entry);
  136.         entry.ftNewFontID = entry.ftOldFontID = pStyle->info.runStyle.tsFont;
  137.         entry.ftEncoding = FontToScript(entry.ftOldFontID);
  138.         entry.ftNameOffset = fontNameOffset;
  139.         fontNameOffset += fontNameSize;
  140.  
  141.         //    add a new entry to the font table
  142.         pFontTable = * (WEFontTableHandle) hFontTable;
  143.         if ((err = _WESplice(hFontTable, &entry, sizeof(entry),
  144.                 sizeof(WEFontTableHeader) + sizeof(WEFontTableEntry) * fontCount)) != noErr)
  145.         {
  146.             goto cleanup;
  147.         }
  148.         fontCount++;
  149.  
  150.         //    mark all remaining entries in the style table which reference
  151.         //    the font ID we have just processed, so that we'll skip them
  152.         for (     styleIndex2 = styleIndex + 1, pStyle2 = pStyle + 1;
  153.                 styleIndex2 < nStyles;
  154.                 styleIndex2++, pStyle2++ )
  155.         {
  156.             if (pStyle2->info.runStyle.tsFont == entry.ftOldFontID)
  157.             {
  158.                 pStyle2->refCount = 0;
  159.             }
  160.         }
  161.     }    // for
  162.  
  163.     //    save font count in font table header
  164.     pFontTable = * (WEFontTableHandle) hFontTable;
  165.     pFontTable->ftHeader.ftNumEntries = fontCount;
  166.  
  167.     //    adjust name offsets in the font table
  168.     offsetAdjustment = sizeof(WEFontTableEntry) * fontCount;
  169.     for (    pEntry = &pFontTable->ftEntries[0];
  170.             fontCount > 0;
  171.             fontCount--, pEntry++ )
  172.     {
  173.         pEntry->ftNameOffset += offsetAdjustment;
  174.     }
  175.  
  176.     //    clear result code
  177.     err = noErr;
  178.  
  179. cleanup:
  180.     _WEForgetHandle(&hStyles);
  181.  
  182.     //    return result code
  183.     return err;
  184. }
  185.  
  186. pascal OSErr WEUpdateFontTable(Handle hFontTable, WEFontNameToIDUPP fontNameToIDProc, Boolean *wasChanged)
  187. {
  188.     WEFontTablePtr pFontTable;
  189.     WEFontTableEntryPtr pEntry;
  190.     ConstStr255Param fontName;
  191.     Size fontTableSize;
  192.     SInt32 fontCount;
  193.     Str255 systemFontName;
  194.     Boolean saveFontTableLock, changed;
  195.     OSErr err;
  196.  
  197.     //    assume font table won't change
  198.     changed = false;
  199.  
  200.     //    return an error code is hFontTable is nil
  201.     err = nilHandleErr;
  202.     if (hFontTable == nil)
  203.     {
  204.         goto cleanup;
  205.     }
  206.  
  207.     //    lock the font table
  208.     saveFontTableLock = _WESetHandleLock(hFontTable, true);
  209.     pFontTable = * (WEFontTableHandle) hFontTable;
  210.  
  211.     //    make sure the font table is a reasonable size
  212.     fontTableSize = GetHandleSize(hFontTable);
  213.     err = weCorruptDataErr;
  214.     if (fontTableSize < sizeof(WEFontTableHeader))
  215.     {
  216.         goto cleanup;
  217.     }
  218.  
  219.     //    check font table signature and entry count
  220.     if (pFontTable->ftHeader.ftSignature != weFontTableSignature)
  221.     {
  222.         goto cleanup;
  223.     }
  224.     if (fontTableSize < sizeof(WEFontTableHeader) + sizeof(WEFontTableEntry) * pFontTable->ftHeader.ftNumEntries)
  225.     {
  226.         goto cleanup;
  227.     }
  228.  
  229.     //    check font table version
  230.     //    assume we know how to handle all 1.x versions
  231.     //    if a new, incompatible format is designed in the future, it will
  232.     //    have to bump the version number to 2.x so this code can safely skip it
  233.     err = weNewerVersionErr;
  234.     if ((pFontTable->ftHeader.ftVersion & 0xFF000000) != 0x01000000)
  235.     {
  236.         goto cleanup;
  237.     }
  238.  
  239.     //    get name of system font
  240.     GetFontName(systemFont, systemFontName);
  241.  
  242.     //    walk the font table
  243.     for (    fontCount = pFontTable->ftHeader.ftNumEntries,
  244.             pEntry = &pFontTable->ftEntries[0];
  245.             fontCount > 0 ;
  246.             fontCount--, pEntry++ )
  247.     {
  248.         //    calculate pointer to font name
  249.         fontName = (ConstStr255Param) (((UInt32) pFontTable) + pEntry->ftNameOffset);
  250.  
  251.         //    by default, map font name to font ID using GetFNum()
  252.         GetFNum(fontName, &pEntry->ftNewFontID);
  253.  
  254.         //    GetFNum() returns zero either because the specified font
  255.         //    is the system font, or because it doesn't exist
  256.         if ((pEntry->ftNewFontID == 0) && !EqualString(fontName, systemFontName, false, false))
  257.         {
  258.             //    missing font:
  259.             //    use a replacement font with the same character encoding, if possible
  260.             pEntry->ftNewFontID = GetScriptVariable(GetScriptVariable(pEntry->ftEncoding,
  261.                         smEnabled) ? pEntry->ftEncoding : smSystemScript, smScriptAppFond);
  262.         }
  263.  
  264.         //    caller can customize the name resolution process
  265.         //    by specifying a mapping function
  266.         if (fontNameToIDProc != nil)
  267.         {
  268.             //    map font name to font ID using the supplied mapping function
  269.             if ((err = CallWEFontNameToIDProc(fontName, pEntry->ftOldFontID, &pEntry->ftNewFontID, fontNameToIDProc)) != noErr)
  270.             {
  271.                 goto cleanup;
  272.             }
  273.         }
  274.  
  275.         if (pEntry->ftOldFontID != pEntry->ftNewFontID)
  276.         {
  277.             changed = true;
  278.         }
  279.     }    //    for
  280.  
  281.     //    clear result code
  282.     err = noErr;
  283.  
  284. cleanup:
  285.     //    unlock the font table
  286.     if (hFontTable != nil)
  287.     {
  288.         _WESetHandleLock(hFontTable, saveFontTableLock);
  289.     }
  290.  
  291.     //    return wasChanged flag
  292.     if (wasChanged != nil)
  293.     {
  294.         *wasChanged = changed;
  295.     }
  296.  
  297.     //    return result code
  298.     return err;
  299. }
  300.  
  301. pascal OSErr WEUpdateStyleScrap(StScrpHandle hStyles, Handle hFontTable)
  302. {
  303.     WEFontTablePtr pFontTable;
  304.     WEFontTableEntryPtr pEntry;
  305.     ScrpSTElement *pStyle;
  306.     SInt32 fontCount, styleCount;
  307.     SInt16 oldFontID, newFontID;
  308.  
  309.     //    this function doesn't move memory, so we can
  310.     //    safely dereference hFontTable without locking it
  311.     pFontTable = * (WEFontTableHandle) hFontTable;
  312.  
  313.     //    remap font IDs in the style table associated with the specified WE instance
  314.     for (    fontCount = pFontTable->ftHeader.ftNumEntries,
  315.             pEntry = &pFontTable->ftEntries[0];
  316.             fontCount > 0 ;
  317.             fontCount--, pEntry++ )
  318.     {
  319.         oldFontID = pEntry->ftOldFontID;
  320.         newFontID = pEntry->ftNewFontID;
  321.  
  322.         //    skip inner loop if there's nothing to change
  323.         if (oldFontID == newFontID)
  324.         {
  325.             continue;
  326.         }
  327.  
  328.         for (    styleCount = (*hStyles)->scrpNStyles,
  329.                 pStyle = & (*hStyles)->scrpStyleTab[0];
  330.                 styleCount > 0;
  331.                 styleCount--, pStyle++ )
  332.         {
  333.             if (pStyle->scrpFont == oldFontID)
  334.             {
  335.                 pStyle->scrpFont = newFontID;
  336.             }
  337.         }    //    for
  338.     }    //    for
  339.  
  340.     return noErr;
  341. }
  342.